package com.xframe.xdal.core.model;


import com.xframe.xdal.core.handler.BeanHandlerOptions;
import com.xframe.xdal.core.handler.IBeanListHandlerCallBack;
import com.xframe.xdal.core.serialize.BaseJsonSer;
import com.xframe.xdal.core.serialize.IJSONSer;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.springframework.lang.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * 功能描述:完成属性名称和数据库表名称的转换，支持多级
 *
 * @author xufeng
 * @version 1.0
 * @date 2022-09-26
 */
@Data
@Accessors(chain=true)
public class FindOptions {


    /**
     * 查询条件
     */
    private ConditionValueCollection conditionValueCollection = new ConditionValueCollection();

    /**
     * 添加查询条件
     * @param conditionValue 查询条件
     */
    public FindOptions addConditionValue(ConditionValue conditionValue){
        if(conditionValueCollection == null){
            conditionValueCollection = new ConditionValueCollection();
        }
        this.conditionValueCollection.add(conditionValue);
        return this;
    }
    /**
     * 排序对象
     */
    private DbSortCollection dbSortCollection = new DbSortCollection();

    /**
     * 添加排序对象
     * @param dbSort 排序对象
     */
    public FindOptions addDbSort(DbSort dbSort){
        if(dbSortCollection == null){
            dbSortCollection = new DbSortCollection();
        }
        dbSortCollection.add(dbSort);
        return this;
    }

    /**
     * 是否查询需要限制最大记录条数
     */
    private int dataMaxCount = -1;
    /**
     * 引用的名称集合
     */
    private List<String> refList = new ArrayList<>();
    /**
     * 添加引用关系名称
     * @param refName 引用关系名称
     */
    public FindOptions addRef(String refName){
        if(refList == null){
            refList = new ArrayList();
        }
        refList.add(refName);
        return this;
    }
    /**
     * 分页索引
     */
    private int pageIndex = 0;
    /**
     * 页容量
     */
    private int pageSize = 100;
    /**
     * 是否设置总记录数
     */
    private Boolean recordCountFlag = false;


    /**
     * 查询rsHandler的设置对象
     */
    @Getter(AccessLevel.PUBLIC)
    @Setter(AccessLevel.PRIVATE)
    private BeanHandlerOptions beanHandlerOptions;

    /**
     * 集合的类型
     */
    public FindOptions setCollectionType(Class<?> dataType){
        if(beanHandlerOptions == null){
            beanHandlerOptions = new BeanHandlerOptions();
        }
        beanHandlerOptions.setCollectionType(dataType);
        return this;
    }
    /**
     * 定义模型的KEY接口
     */
    public FindOptions setModelMapKey(IModelMapKey modelMapKey){
        if(beanHandlerOptions == null){
            beanHandlerOptions = new BeanHandlerOptions();
        }
        beanHandlerOptions.setModelMapKey(modelMapKey);
        return this;
    }
    /**
     * 查询的过滤接口
     */
    public FindOptions setBeanListHandlerCallBack(IBeanListHandlerCallBack callBack){
        if(beanHandlerOptions == null){
            beanHandlerOptions = new BeanHandlerOptions();
        }
        beanHandlerOptions.setBeanListHandlerCallBack(callBack);
        return this;
    }

    /**
     * JSON序列化的
     */
    private IJSONSer jsonSer = new BaseJsonSer();



    public boolean hasPageArgs(){
        return this.pageIndex >= 1 && pageSize > 1;
    }

    public boolean hasDataMaxCount(){
        return this.dataMaxCount >= 1;
    }


    public static FindOptions defFindAllOptions(){
        return FindOptions.valueOf(null,null,null);
    }

    public static FindOptions defFindAllOptionsByMaxCount(){
        FindOptions options = new FindOptions();
        options.pageIndex = 1;
        options.pageSize = 20;
        options.dataMaxCount = 1000;
        options.recordCountFlag = false;
        options.conditionValueCollection = new ConditionValueCollection();
        options.dbSortCollection = new DbSortCollection();
        return options;
    }
    /**
     * 是否设置总记录数
     */
    public static FindOptions defFindAllOptionsByPage(){
        FindOptions options = new FindOptions();
        options.pageIndex = 1;
        options.pageSize = 20;
        options.dataMaxCount = 0;
        options.recordCountFlag = true;
        options.conditionValueCollection = new ConditionValueCollection();
        options.dbSortCollection = new DbSortCollection();
        return options;
    }

    /**
     * 是否设置总记录数
     */
    public static FindOptions esFindAllOptions(){
        FindOptions options = new FindOptions();
        options.pageIndex = 0;
        options.pageSize = 1000;
        options.dataMaxCount = 0;
        options.recordCountFlag = true;
        options.conditionValueCollection = new ConditionValueCollection();
        options.dbSortCollection = new DbSortCollection();
        return options;
    }
    /**
     * 构造一个分页查询设置对象
     * @param pageIndex 页面索引
     * @param pageSize  页面容量
     * @param setRecordCountFlag  是否设置最大记录条数
     * @param conditionValueCollection  查询条件
     * @param refList  引用列表
     * @param dbSorts  排序表达式
     */
    public static FindOptions valueOf(int pageIndex,int pageSize,@Nullable Boolean setRecordCountFlag,
                                      @Nullable ConditionValueCollection conditionValueCollection,
                                      @Nullable List<String> refList,
                                      @Nullable DbSort... dbSorts){
        assert pageIndex > 1 && pageSize > 1;
        FindOptions options = new FindOptions();
        options.pageIndex = pageIndex;
        options.pageSize = pageSize;
        options.dataMaxCount = 0;
        if(setRecordCountFlag != null) {
            options.recordCountFlag = setRecordCountFlag;
        }
        if(refList != null) {
            options.refList = refList;
        }
        if(conditionValueCollection != null) {
            options.conditionValueCollection = conditionValueCollection;
        }
        if(dbSorts != null) {
            options.dbSortCollection = new DbSortCollection(dbSorts);
        }
        return options;
    }

    /**
     * 构造一个查询设置对象
     * @param conditionValueCollection  查询条件
     * @param refList  引用列表
     * @param dbSorts  排序表达式
     */
    public static FindOptions valueOf(@Nullable ConditionValueCollection conditionValueCollection,
                                            @Nullable List<String> refList,
                                            @Nullable DbSort... dbSorts){
        FindOptions options = new FindOptions();
        options.pageIndex = 0;
        options.pageSize = -1;
        options.dataMaxCount = -1;
        options.recordCountFlag = false;
        if(refList != null) {
            options.refList = refList;
        }
        if(conditionValueCollection != null) {
            options.conditionValueCollection = conditionValueCollection;
        }
        if(dbSorts != null) {
            options.dbSortCollection = new DbSortCollection(dbSorts);
        }
        return options;
    }

}
